package com.ibm.broker.as400plugin;


import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400ConnectionPool;
import com.ibm.as400.access.DataQueue;
import com.ibm.as400.access.DataQueueEntry;
import com.ibm.as400.access.QSYSObjectPathName;


import com.ibm.broker.plugin.*;

public class as400iNode extends MbInputNode implements MbInputNodeInterface {

	

	int creado = 0;
	int contador = 0;
	private DataQueueEntry kdqe = null;
	
	private String host;
	private String user;
	private String password;
	private String libDTQ;
	private String nameDTQ;
	private int logLevel;
	private int numConn;
	
	private AS400ConnectionPool as400Pool;
	private QSYSObjectPathName pathIn = null;
	
	
	private LogTraceData logdt = null;
	
	private MbMessage outMessage;
	
	
	// Constructor 
	public as400iNode() throws MbException {
		// create terminals here
		createOutputTerminal("catch");		
		createOutputTerminal("out");
		createOutputTerminal("failure");
		
		logdt = new LogTraceData("as400i.log");		
			
	}
	
	
	// ---------------------------------	
	// WMQI Node name
	public static String getNodeName() {
		return "as400iNode";
	}
	// ---------------------------------	
	// FTP command port accessors

	// ---------------------------------	
	// WMQI input node execution loop
	public int run(MbMessageAssembly assembly) throws MbException {
       
		DataQueue kdqIn = null;
		AS400 as400 = null;
		
		logdt.setlogDataLevel(this.getLogLevel());
		
		logdt.logData_Debug("Ejecucion del Run");
		
		outMessage = new MbMessage();
		
		kdqe = null;
		logdt.logData_Debug("antes try");
		try 
		{
			if (creado == 0){
				logdt.logData_Info("creado = 0");
		        
				contador = 0;
				logdt.logData_Info("numero conexiones: "+numConn);
				as400Pool = new AS400ConnectionPool();
				as400Pool.setMaxConnections(numConn+1);//Maximo Numero de conexiones
				as400Pool.setMaxLifetime(1000*60*2);//tirempo maxiomo de vida 30min
				as400Pool.fill(host, user, password, AS400.DATAQUEUE, numConn);//crea n conexiones
				
						
				//as400 = new AS400(host, user, password);
	        	pathIn = new QSYSObjectPathName(libDTQ, nameDTQ, "DTAQ");
				
				creado = 1;
				logdt.logData_Debug("Se iniciaron las variables de conexion");
				
			}
			logdt.logData_Debug("Number of active connections: " +
			as400Pool.getActiveConnectionCount(host, user));
			logdt.logData_Debug("Number of available connections for use: " +
			as400Pool.getAvailableConnectionCount(host, user));
					
			as400 = as400Pool.getConnection(host, user, password,AS400.DATAQUEUE);
			
			logdt.logData_Debug("Number of active connections: " +
			as400Pool.getActiveConnectionCount(host, user));
			logdt.logData_Debug("Number of available connections for use: " +
			as400Pool.getAvailableConnectionCount(host, user));
			
			kdqIn = new DataQueue(as400, pathIn.getPath());		
			
			
			logdt.logData_Debug("AS400:"+as400.toString());
			kdqe = kdqIn.read();
			as400Pool.returnConnectionToPool(as400);
			if (kdqe != null) {
	        	logdt.logData_Debug("Se leyo el mensaje");
	        	logdt.logData_Info("Mensaje: "+ kdqe.getData());
	    		contador = contador +1;
				logdt.logData_Info("contador:"+contador);
				enviarMensaje(assembly, kdqe);
			}else{
				logdt.logData_Debug("No hay mensaje::timeout");
				return TIMEOUT;
			}
			
	        
		}catch (MbBrokerException mbbe) {
			// TODO: handle exception
			logdt.logData_Error("Error Metodo Run MbBrokerException:: ", mbbe);
			if (creado == 1)
				as400Pool.returnConnectionToPool(as400);
			MbMessageAssembly outputAssembly = new MbMessageAssembly(assembly, outMessage);
			logdt.crearMessageEXC(outputAssembly, mbbe);
			dispatchThread();
			getOutputTerminal("failure").propagate(outputAssembly);
			mbbe.printStackTrace();
			return FAILURE_RETURN;
			
			
		}catch (Exception e) {
			logdt.logData_Error("Error Metodo Run :: ",e);
			if (creado == 1)
				as400Pool.returnConnectionToPool(as400);
			MbMessageAssembly outputAssembly = new MbMessageAssembly(assembly, outMessage);
			logdt.crearMessageEXC(outputAssembly,e);
			dispatchThread();
			getOutputTerminal("failure").propagate(outputAssembly);
			e.printStackTrace();
			return FAILURE_RETURN;
			

		} 
		return SUCCESS_RETURN;
	}
	// ---------------------------------			
	// The AS400I server command processor
	private void enviarMensaje(MbMessageAssembly assembly, DataQueueEntry info) throws Exception {
		
		logdt.logData_Debug("Entra Metodo enviarMensaje");
		crearMessageBLOB(info.getData());
		MbMessageAssembly outputAssembly = new MbMessageAssembly(assembly, outMessage);
		
		try {
			
			MbOutputTerminal terminal1 = getOutputTerminal("out");
			dispatchThread();
			terminal1.propagate(outputAssembly);
			logdt.logData_Info("Mensaje enviado terminal out");
			
			outMessage.clearMessage();
			
		}catch (MbBrokerException mbbe) {
			// TODO: handle exception
			logdt.logData_Error("Error Metodo enviarMensaje MbBrokerException:: ");
			throw mbbe;
		}catch (Exception e) {
			logdt.logData_Error("Error Metodo enviarMensaje Exception:: ",e);
			e.printStackTrace();
			throw e;
		}
		
	}
	
	public void crearMessageBLOB(byte[] info)throws Exception{
		
		logdt.logData_Debug("entra al metodo crearMessageBLOB(Bytes)");
		try{
			//outMessage.clearMessage();
			MbElement outRoot = outMessage.getRootElement();
			MbElement aux = outRoot.getFirstChild();
			while (aux != null){
				logdt.logData_Info("Nombre Nodo: "+ aux.getName());
				aux.detach();
				aux = outRoot.getFirstChild();
			}
			
			MbElement PROP = outRoot.createElementAsLastChild("Properties");
			PROP.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Encoding", 273);
			PROP.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "CodedCharSetId", 819);
			logdt.logData_Debug("creaProperties");
			MbElement MQMD = outRoot.createElementAsLastChild(MbMQMD.PARSER_NAME);	
			MQMD.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Encoding", 273);
			MQMD.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "CodedCharSetId", 819);
			logdt.logData_Debug("creaMQMD");
			MbElement BLOB = outRoot.createElementAsLastChild(MbBLOB.PARSER_NAME);	 		
			BLOB.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", info);  		
			logdt.logData_Debug("creaBLOB");
			outMessage.finalizeMessage(MbMessage.FINALIZE_VALIDATE);
			
			
		} catch (Exception e) {
			logdt.logData_Error("Error creando mensaje BLOB(Bytes)",e);	
			e.printStackTrace();
			throw e;
		}
	}
	
	public void crearMessageBLOB(String info){
		
		logdt.logData_Debug("entra al metodo crearMessageBLOB(String)");
		try{
			//outMessage.clearMessage();
			MbElement outRoot = outMessage.getRootElement();
			MbElement PROP = outRoot.createElementAsFirstChild("Properties");
			PROP.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Encoding", 273);
			PROP.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "CodedCharSetId", 819);
			logdt.logData_Debug("creaProperties");
			MbElement MQMD = outRoot.createElementAsLastChild(MbMQMD.PARSER_NAME);	
			MQMD.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Encoding", 273);
			MQMD.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "CodedCharSetId", 819);
			logdt.logData_Debug("creaMQMD");
			MbElement BLOB = outRoot.createElementAsLastChild(MbBLOB.PARSER_NAME);	 		
			BLOB.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "BLOB", info.getBytes());  		
			logdt.logData_Debug("creaBLOB");
			outMessage.finalizeMessage(MbMessage.FINALIZE_VALIDATE);
			
		
		} catch (Exception e) {
			logdt.logData_Error("Error creando mensaje BLOB(String)",e);	
			e.printStackTrace();
		}
	}

	
	
	public void onDelete() {
		
		if (creado == 1)
			as400Pool.close();
		
		logdt.logData_Debug("Eliminando Conexiones");
		creado = 0;
		}
	
	
	public String getHost() {
		
		return (this.host);
	}
	
	public void setHost(String host) {
		
		this.host=host;
	}
	
	public String getUser() {
		
		return (this.user);
	}
	
	public void setUser(String user) {
		
		this.user=user;
	}
	public String getPassword() {
		
		return (this.password);
	}
	
	public void setPassword(String password) {
		
		this.password=password;
	}
	
	public String getLibDTQ() {
		
		return (this.libDTQ);
	}
	
	public void setLibDTQ(String libDTQ) {
		
		this.libDTQ=libDTQ;
	}
	
	public String getNameDTQ() {
		
		return (this.nameDTQ);
	}
	
	public void setNameDTQ(String nameDTQ) {
		
		this.nameDTQ=nameDTQ;
	}
	
	public String getNumeroConexiones() {
		
		return (String.valueOf(this.numConn));
	}
	
	public void setNumeroConexiones(String nameDTQ) {
		
		
		this.numConn =Integer.parseInt(nameDTQ) ;
	}
	
	public String getLogLevel()
	{
		String level = null;
		
		switch (logLevel)
		{
			case LogTraceData.LOGDATA_LEVEL_NONE: 
										level = "NONE";
										break;
			case LogTraceData.LOGDATA_LEVEL_DEBUG:
										level = "DEBUG";
										break;
			case LogTraceData.LOGDATA_LEVEL_INFO:
			 							level = "INFO";
										break;
			case LogTraceData.LOGDATA_LEVEL_ERROR:
										level = "ERROR";
										break;
		}		
		return level;	
	}
	
	/*for node properties attribute 'logLevel' used by broker*/
	
	public void setLogLevel(String level)
	{
		if(level == null) return;
		
		if(level.equals("NONE"))
			logLevel = LogTraceData.LOGDATA_LEVEL_NONE;
		else if(level.equals("DEBUG")) 
			logLevel = LogTraceData.LOGDATA_LEVEL_DEBUG;
		else if(level.equals("INFO")) 
			logLevel = LogTraceData.LOGDATA_LEVEL_INFO;
		else if(level.equals("ERROR"))
			logLevel = LogTraceData.LOGDATA_LEVEL_ERROR;
	}
	
	/*
	 * This function need to be called only once as part of initializing the node...
	 * */	
	public void printMessage(MbMessage exp){
		String valor;
		try{
			MbElement ele = exp.getRootElement();
			logdt.logData_Info("Nombre Root: "+ ele.getName());
			valor = new String(exp.getBuffer());
			logdt.logData_Info("Valor: "+ valor);
			/*
			while (ele != null){
				logdt.logData_Info("Nombre: "+ ele.getName());
				ele = ele.;
				ele.
			}*/
		}catch (Exception e) {
			logdt.logData_Info("FALLO print: "+ e.toString());
		}
	}
	
}